/*
 * LPBConvertMain.cpp
 *
 * Copyright 2012 Fabian Wenzelmann, Christian Schilling
 *
 * This file is part of Recognition-Procedures-for-Boolean-Functions.
 *
 * Recognition-Procedures-for-Boolean-Functions is free software: you
 * can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * Recognition-Procedures-for-Boolean-Functions is distributed in the hope
 * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
 * Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Recognition-Procedures-for-Boolean-Functions.
 *
 * If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>
#include <fstream>

#include <boost/filesystem.hpp>

#include "bfr/LPBParser.hpp"
#include "bfr/ClauseSet.hpp"

using namespace std;
using namespace boost::filesystem;
using namespace bfr;

LPBParser parser;

void translate(const path &inFile, const path &outPath);
void translate_collection(const path &inFile, const path &outPath);

int main(int argc, char** argv) {
    if (argc != 3) {
        cerr << "Expecting exactly two arguments:" << endl;
        cerr << argv[0] << " <IN> <OUT>" << endl;
        cerr << "Where <IN> is either a file or directory and <OUT> is a "
                "directory." << endl;
        return 1;
    }
    path in(argv[1]);
    path out(argv[2]);
    if (!exists(in)) {
        cerr << "File " << in << " does not exist." << endl;
        return 1;
    }
    if (!exists(out)) {
        cerr << "File " << out << " does not exist." << endl;
        return 1;
    }
    if (!is_directory(out)) {
        cerr << "<OUT> object must be a directory." << endl;
        return 1;
    }
    if (is_directory(in)) {
        directory_iterator end_it;
        for (directory_iterator it(in); it != end_it; it++) {
            path next = *it;
            if (is_directory(next) || !(next.extension().string() == ".lpb")) {
                continue;
            }
            translate(*it, out);
        }
    }
    else {
      if (in.extension().string() == ".lpbs") {
	translate_collection(in, out); } else {
        translate(in, out);
      }
    }
    return 0;
}

void translate(const path &inFile, const path &outPath) {
    path outFileName = inFile.stem().replace_extension(".dnf");
    path out = outPath / outFileName;
    ifstream inStream;
    inStream.open(inFile.c_str());
    ofstream outStream;
    outStream.open(out.c_str());
    LPB *lpb = parser.parse(inStream);
    ClauseSet *dnf = lpb->toDNF();
    dnf->writeDIMACS(outStream);
    inStream.close();
    outStream.close();
    delete lpb;
    delete dnf;
}

void translate_collection(const path &inFile, const path &outPath) {
  path outFileName = inFile.stem().replace_extension(".dnfs");
  path out = outPath / outFileName;
  ClauseSet *dnf;
  ifstream inStream;
  inStream.open(inFile.c_str());
  ofstream outStream;
  outStream.open(out.c_str());
  std::vector<LPB*> *lpbs = parser.parse_collection(inStream);
  for (std::vector<LPB*>::const_iterator it = lpbs->begin(); it != lpbs->end(); ++it)
    {
      dnf = (*it)->toDNF();
      dnf->writeDIMACS(outStream);
    }
  inStream.close();
  outStream.close();
  delete lpbs;
  delete dnf;
}
